home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / mail / berolist.0 / berolist / BeroList-1.0.1 / list.c < prev    next >
C/C++ Source or Header  |  1996-05-21  |  14KB  |  511 lines

  1. /* BeroList 1.0.0                                                 */
  2. /* An easy-to-use mailing list server                             */
  3. /* (c) 1996 by Bernhard Rosenkraenzer <root@startrek.in-trier.de> */
  4. /* Fixed by Jarno Paananen <jpaana@kalahari.ton.tut.fi>           */
  5.  
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include "list.h"
  10. #ifndef HOST
  11.     #include <unistd.h>
  12.       char *hostname;
  13.       #define HOST hostname
  14.       #define GET_HOST
  15. #endif
  16. #ifdef LOG
  17.     FILE *log;
  18. #endif
  19. char *listaddress;
  20.  
  21. /* Function prototypes... */
  22.  
  23. char *extract(char *from, const char *begin, const char end);
  24. char *readfile(char *filename);
  25. char *readline(FILE *file);
  26. void send(char *list, char *to, char *from, char *subject, char *message, char *footfile);
  27. void sendtolist(char *listname, char *from, char *subject, char *message);
  28. void subscribe(char *listname, char *user, char *operator);
  29. void unsubscribe(char *listname, char *user, char *operator);
  30. char *email(char *full_address);
  31. char *realname(char *full_address);
  32. char *username(char *address);
  33. int scasecmp(char *s1, char *s2); /* Fix a buggy implementation of strcasecmp */
  34.  
  35. /* Functions... */
  36.  
  37. char *extract(char *from, const char *begin, const char end)
  38. {
  39.   char *found;
  40.  
  41.   if((char *)strstr(from,begin)!=NULL) {
  42.       found=(char *) malloc(strlen(from) + 1);
  43.       strcpy(found,(char *) strstr(from,begin)+strlen(begin));
  44.       if((char *) strchr(found,end)!=NULL)
  45.           found[strchr(found,end)-found]='\0';
  46.       if((char *) strchr(found,'\n')!=NULL)
  47.           found[strchr(found,'\n')-found]='\0';
  48.       return(found);
  49.   } else
  50.       return(NULL);
  51. }
  52.  
  53. char *readfile(char *filename)
  54. {
  55.   FILE *in;
  56.   char *content;
  57.   register int size;
  58.   register int flen;
  59.  
  60.   size=1024; flen=0;
  61.   in=fopen(filename,"r");
  62.   if(in!=NULL) {
  63.     content=(char *) malloc(sizeof(char)*(size+1));
  64.     while(!feof(in)) {
  65.           content[flen]=(char) fgetc(in);
  66.           if(flen==size) {
  67.               content[flen+1]='\0';
  68.               size+=2048;
  69.             content=(char *) realloc(content, sizeof(char)*(size+1));
  70.         }
  71.         flen++;
  72.     }
  73.     content[flen-1]='\0';
  74.     fclose(in);
  75.     return(content);
  76.   } else return(NULL);
  77. }
  78.  
  79. char *readline(FILE *file)
  80. {
  81.   char *line;
  82.   register char last;
  83.   register int len;
  84.   
  85.   line=(char *) malloc(sizeof(char)*1024);
  86.   last=0; len=0;
  87.   while(!feof(file) && last!='\n') {
  88.       last=(char) fgetc(file);
  89.       if(last!='\n' && !feof(file)) {
  90.           line[len]=last;
  91.           len++;
  92.       }
  93.   }
  94.   line[len]='\0';
  95.   return(line);
  96. }  
  97.  
  98. void send(char *list, char *to, char *from, char *subject, char *message, char *footfile)
  99. {
  100.   FILE *mailer;
  101.   char *mailer_cmd,*footer;
  102.   
  103.   printf("Sending...\n");
  104.  
  105.   #ifdef TRUSTED
  106.       from=email(from);
  107.       mailer_cmd=(char *) malloc(strlen(SENDMAIL)+strlen(from)+strlen(to)+7);
  108.     sprintf(mailer_cmd,"%s -f%s '%s'",SENDMAIL,from,to);
  109.     #ifdef LOG
  110.           fprintf(log,"* %s\n",mailer_cmd);
  111.       #endif
  112.       mailer=popen(mailer_cmd,"w");
  113.   #else
  114.     mailer_cmd=(char *) malloc(strlen(SENDMAIL)+strlen(to)+4);
  115.     sprintf(mailer_cmd,"%s '%s'",SENDMAIL,to); 
  116.     #ifdef LOG
  117.         fprintf(log,"* %s\n",mailer_cmd);
  118.     #endif
  119.     mailer=popen(mailer_cmd,"w");
  120.     fprintf(mailer,"From: %s\n",from);
  121.   #endif
  122.   if(subject==NULL && strncasecmp(message,"subject:",8)==0) {
  123.     /* Subject: line @ beginning of msg body... */
  124.     subject=(char *) malloc(strlen(message)-7);
  125.     strcpy(subject,message+8);
  126.     while(strchr(subject,' ')==subject) subject++;
  127.     subject[strchr(subject,' ')-subject]='\0';
  128.     message=strchr(message,'\n')+1;
  129.   }
  130.   if(subject!=NULL)    fprintf(mailer,"Subject: %s\n",subject);
  131.   fprintf(mailer,"\n%s\n",message);
  132.   footer=readfile(footfile);
  133.   if(footer!=NULL)    fprintf(mailer,"%s\n",footer);
  134.   fprintf(mailer,".\n");
  135.   pclose(mailer);  
  136. }
  137.  
  138. void sendtolist(char *listname, char *from, char *subject, char *message)
  139. {
  140.   char *listfile,*footfile,*conffile,*member;
  141.   char *oldmsg;
  142.   char *config,*sender;
  143.   FILE *list;
  144.  
  145.   printf("Sending to list...\n");
  146.   
  147.   listfile=(char *) malloc(strlen(LISTDIR)+strlen(listname)+10);
  148.   sprintf(listfile,"%s/%s.members",LISTDIR,listname);
  149.   footfile=(char *) malloc(strlen(LISTDIR)+strlen(listname)+9);
  150.   sprintf(footfile,"%s/%s.footer",LISTDIR,listname);
  151.   conffile=(char *) malloc(strlen(LISTDIR)+strlen(listname)+9);
  152.   sprintf(conffile,"%s/%s.config",LISTDIR,listname);
  153.   
  154.   config=readfile(conffile);
  155.   sender=extract(config,"sender=",'\n');
  156.   if((scasecmp(sender,"original")==0) || sender==NULL)
  157.       sender=from;
  158.   if(scasecmp(sender,"list")==0) 
  159.         sender=listaddress;
  160.         
  161.   #ifndef NO_SENDER_ADDRESS
  162.     if(scasecmp(email(sender),email(from))) { /* sender != original sender */ 
  163.         oldmsg=message;
  164.         message=(char *) malloc(strlen(from)+strlen(message)+15);
  165.           sprintf(message,"* From: %s\n\n%s",from,oldmsg);
  166.       }
  167.   #endif
  168.   #ifndef NO_LIST_ADDRESS
  169.       if(scasecmp(listaddress,email(sender))) { /* sender != list */
  170.           oldmsg=message;
  171.           message=(char *) malloc(strlen(listaddress)+strlen(message)+15);
  172.           sprintf(message,"* List: %s\n\n%s",listaddress,oldmsg);
  173.       }
  174.   #endif
  175.  
  176.   list=fopen(listfile,"r");
  177.   while(!feof(list)) {
  178.       member=readline(list);
  179.       if(strlen(member)>2)
  180.           send(listname,member,sender,subject,message,footfile);
  181.       free(member);
  182.   }
  183.   fclose(list);
  184.   free(listfile); free(footfile); free(conffile);
  185. }
  186.  
  187. void subscribe(char *listname, char *user, char *operator)
  188. {
  189.   FILE *list;
  190.   char *mail,*from;
  191.   char *listfile,*footfile,*welcfile;
  192.  
  193.   #ifdef LOG
  194.     if(operator==NULL)
  195.           fprintf(log,"* subscribing %s\n",user);
  196.     else
  197.         fprintf(log,"* %s subscribed by %s\n",user,operator);
  198.   #endif
  199.  
  200.   listfile=(char *) malloc(strlen(LISTDIR)+strlen(listname)+10);
  201.   sprintf(listfile,"%s/%s.members",LISTDIR,listname);
  202.   welcfile=(char *) malloc(strlen(LISTDIR)+strlen(listname)+10);
  203.   sprintf(welcfile,"%s/%s.welcome",LISTDIR,listname);
  204.   footfile=(char *) malloc(strlen(LISTDIR)+strlen(listname)+9);
  205.   sprintf(footfile,"%s/%s.footer",LISTDIR,listname);
  206.  
  207.   list=fopen(listfile,"a");
  208.   fprintf(list,"%s\n",user);
  209.   fclose(list);
  210.   mail=readfile(welcfile);
  211.   if(mail!=NULL) {
  212.     #ifdef LOG
  213.         fprintf(log,"* sending welcome message\n");
  214.     #endif
  215.     if(operator!=NULL)
  216.         send(listname,user,operator,NULL,mail,footfile);
  217.     else {
  218.         from=(char *) malloc(1024);
  219.         sprintf(from,"%s@%s",listname,HOST);
  220.         send(listname,user,from,NULL,mail,footfile);
  221.         free(from);
  222.     }
  223.     free(mail);
  224.   }
  225.   free(footfile);  free(welcfile);  free(listfile);
  226. }
  227.  
  228. void unsubscribe(char *listname, char *user, char *operator)
  229. {
  230.   char *listfile;
  231.   FILE *list;
  232.   register int members,i;
  233.   char *member[MAX_MEMBERS];
  234.   
  235.   listfile=(char *) malloc(strlen(LISTDIR)+strlen(listname)+10);
  236.   sprintf(listfile,"%s/%s.members",LISTDIR,listname);
  237.   
  238.   #ifdef LOG
  239.       if(operator==NULL)
  240.           fprintf(log,"* %s unsubscribed\n",user);
  241.       else
  242.           fprintf(log,"* %s unsubscribed by %s\n",user,operator);
  243.   #endif
  244.  
  245.   list=fopen(listfile,"r");
  246.   members=0;
  247.   while(!feof(list)) {
  248.     member[members]=readline(list);
  249.     if(scasecmp(member[members],user)!=0) members++;
  250.   }
  251.   members--;
  252.   fclose(list);
  253.   list=fopen(listfile,"w");
  254.   for(i=0;i<=members;i++) {
  255.     if(strlen(member[i])>2) fprintf(list,"%s\n",member[i]);
  256.   }
  257.   fclose(list); 
  258.   free(listfile);
  259. }
  260.  
  261. char *email(char *full_address)
  262. {
  263.   /* Get the plain address part from an e-mail address */
  264.   /* (i.e. remove realname) */
  265.   
  266.   char *addr;
  267.   
  268.   addr=(char *) malloc(strlen(full_address)+1);
  269.   strcpy(addr, full_address);
  270.   
  271.   /* Realname <user@host> type address */
  272.   if(((char *) strchr(addr,'<'))!=NULL) {
  273.       addr=(char *) strchr(addr,'<')+1;
  274.       addr[strchr(addr,'>')-addr]='\0';
  275.   }
  276.   
  277.   /* user@host (Realname) type address */
  278.   if(((char *) strchr(addr,' '))!=NULL)
  279.       addr[strchr(addr,' ')-addr]='\0';
  280.   
  281.   return(addr);
  282.   
  283. }
  284.  
  285. char *realname(char *full_address)
  286. {
  287.   char *name;
  288.   
  289.   name=(char *) malloc(strlen(full_address)+1);
  290.   strcpy(name,full_address);
  291.  
  292.   if(((char *) strchr(name,'<'))!=NULL)
  293.       /* Realname <user@host> type address */
  294.       name[strchr(name,'<')-1-name]='\0';
  295.   else if(((char *) strchr(name,'('))!=NULL) {
  296.       /* user@host (Realname) type address) */
  297.       name=strchr(name,'(')+1;
  298.       name[strchr(name,')')-name]='\0';
  299.   } else
  300.       /* Realname not specified -> use username */
  301.       name[strchr(name,'@')-name]='\0';
  302.   
  303.   return(name);
  304.   
  305. }
  306.  
  307. char *username(char *address)
  308. {
  309.   char *name;
  310.   name=email(address);
  311.   if ( strchr(name,'@') != NULL )
  312.     name[strchr(name,'@')-name]='\0';
  313.   return(name);
  314. }
  315.  
  316. int scasecmp(char *s1, char *s2)
  317. {
  318.   if((s1==NULL || s2==NULL)&&(s1!=NULL || s2!=NULL))
  319.       return -1;
  320.   else
  321.       return strcasecmp(s1,s2);
  322. }
  323.  
  324. int main(int argc, char *argv[])
  325. {
  326.   int pos,flen,wsize;
  327.   char *mail,*header,*msg,*to,*from,*errors,*subject,*recipient;
  328.   char *conffile,*listfile,*opfile,*footfile;
  329.   char *config;
  330.   char *a;
  331.   #ifdef LOG
  332.       char *logfile;
  333.   #endif
  334.   
  335.   #ifdef GET_HOST
  336.       hostname=(char *) malloc(1024);
  337.       gethostname(hostname,1024);
  338.       hostname[strlen(hostname)+1]='\0';
  339.       hostname[strlen(hostname)]='.';
  340.       getdomainname(hostname+strlen(hostname),1024-strlen(hostname)-1);
  341.   #endif
  342.   
  343.   printf("%s ready...\n\n",VERSION);
  344.  
  345.   flen=0; wsize=1024;
  346.   mail=(char *) malloc(sizeof(char)*(wsize+1));
  347.   while(!feof(stdin)) {
  348.       mail[flen]=(char) fgetc(stdin);
  349.       if(flen==wsize) {
  350.           mail[flen+1]='\0';
  351.           wsize+=1024;
  352.           mail=(char *) realloc(mail,sizeof(char)*(wsize+1));
  353.       }
  354.       flen++;
  355.   }
  356.   flen--;
  357.   mail[flen]='\0';
  358.   
  359.   header=(char *) malloc(strlen(mail) + 1);
  360.   strcpy(header,mail);
  361.   
  362.   pos=strstr(header,"\n\n")-header;
  363.   header[pos]='\0';
  364.  
  365.   msg=mail+pos+2;
  366.   
  367.   to=email(extract(header,"To: ",'@'));
  368.   from=extract(header,"From: ",'\n');
  369.   subject=extract(header,"Subject: ",'\n');
  370.  
  371.   listaddress=(char *) malloc(strlen(to)+strlen(HOST)+2);
  372.   sprintf(listaddress,"%s@%s",to,HOST);
  373.   
  374.   #ifdef LOG
  375.       logfile=(char *) malloc(strlen(LOGDIR)+strlen(to)+6);
  376.       sprintf(logfile,"%s/%s.log",LOGDIR,to);
  377.     log=fopen(logfile,"a");
  378.     if(log==NULL) {
  379.         printf("can't access log file %s :(\nPlease contact the list operator.\n",logfile);
  380.         return(1);
  381.     }
  382.     fprintf(log,"===================================================\n");
  383.     fprintf(log,"Message '%s' from %s...\n",subject,from);
  384.     fprintf(log,"===================================================\n");
  385.   #endif
  386.  
  387.   /* Find filenames for list... */
  388.   
  389.   listfile=(char *) malloc(strlen(LISTDIR)+strlen(to)+10);
  390.   sprintf(listfile,"%s/%s.members",LISTDIR,to); 
  391.   opfile=(char *) malloc(strlen(LISTDIR)+strlen(to)+12);
  392.   sprintf(opfile,"%s/%s.operators",LISTDIR,to);
  393.   conffile=(char *) malloc(strlen(LISTDIR)+strlen(to)+9);
  394.   sprintf(conffile,"%s/%s.config",LISTDIR,to);
  395.   footfile=(char *) malloc(strlen(LISTDIR)+strlen(to)+9);
  396.   sprintf(footfile,"%s/%s.footer",LISTDIR,to);
  397.   
  398.   /* read config file... */
  399.   
  400.   config=readfile(conffile);
  401.   
  402.   if(strncasecmp(subject,"subscribe ",10)==0) {
  403.       recipient=subject+10;
  404.       a=readfile(opfile);
  405.       if((char *) strstr(a,from)==NULL && scasecmp(email(from),email(recipient))) { /* NO OPERATOR */
  406.           #ifdef LOG
  407.               fprintf(log,"* attempt to subscribe %s by %s\n",recipient,from);
  408.           #endif
  409.           free(mail);
  410.           mail=(char *) malloc(1024);
  411.           sprintf(mail,"You must be list operator in order to add new users to the list %s@%s.",to,HOST);
  412.           send(to,from,listaddress,"List subscription",mail,footfile);
  413.       } else 
  414.           subscribe(to,recipient,from);
  415.   
  416.   } else if(strncasecmp(subject,"unsubscribe ",12)==0) {
  417.       recipient=subject+12;
  418.       a=readfile(opfile);
  419.       if((char *) strstr(a,from)==NULL && scasecmp(email(from),email(recipient))) { /* NO OPERATOR */
  420.           #ifdef LOG
  421.               fprintf(log,"* attempt to unsubscribe %s by %s\n",recipient,from);
  422.           #endif
  423.           free(mail);
  424.           mail=(char *) malloc(1024);
  425.           sprintf(mail,"You must be list operator in order to unsubscribe users.");
  426.           send(to,from,listaddress,"List unsubscription",mail,footfile);
  427.       } else {
  428.           unsubscribe(to,recipient,from);
  429.       }
  430.   } else if(scasecmp(subject,"subscribe")==0) {
  431.       a=extract(config,"newusers=",'\n');
  432.       if(scasecmp(a,"no")==0 && a!=NULL) {  /* Do not accept new users */
  433.           a=extract(config,"contact=",'\n');
  434.           if(a==NULL) {
  435.               a=(char *) malloc(6+strlen(HOST));
  436.               sprintf(a,"root@%s",HOST);
  437.           }
  438.           #ifdef LOG
  439.               fprintf(log,"* %s tried to subscribe\n",from);
  440.           #endif
  441.           free(mail);
  442.           mail=(char *) malloc(1024);
  443.           sprintf(mail,"%s is a closed mailing list. If you wish to subscribe, contact\nthe list operator at %s.\n",to,a);
  444.           send(to,from,listaddress,"List subscribtion",mail,footfile);
  445.       } else {
  446.           subscribe(to,from,NULL);
  447.     }
  448.   } else if(scasecmp(subject,"unsubscribe")==0) {
  449.       unsubscribe(to,from,NULL);
  450.   } else {  /* Mail for list */
  451.       errors=extract(config,"errors-to=",'\n');
  452.       if(errors==NULL) {
  453.           errors=extract(config,"contact=",'\n');
  454.           if(errors==NULL) {
  455.               errors=(char *) malloc(6+strlen(HOST));
  456.               sprintf(errors,"root@%s",HOST);
  457.           }
  458.       }
  459.       if(scasecmp(username(from),"mailer-daemon")==0) {
  460.           #ifdef LOG
  461.               fprintf(log,"* Error message - forwarding to %s.\n",errors);
  462.           #endif
  463.           free(mail);
  464.           mail=(char *) malloc(strlen(VERSION)+1+strlen(msg)+strlen(to)+28);
  465.           sprintf(mail,"%s\nError from mailing list %s:\n\n%s",VERSION,to,msg);
  466.           send(to,errors,from,subject,mail,NULL);
  467.       } else {
  468.             a=extract(config,"closed=",'\n');
  469.           if(scasecmp(a,"yes")==0) {
  470.               a=readfile(listfile);
  471.               if((char *) strstr(a,from)==NULL) { /* NOT member of list */
  472.                   #ifdef LOG
  473.                       fprintf(log,"* Message rejected - %s not member of list.\n",from);
  474.                   #endif
  475.                   a=extract(config,"newusers=",'\n');
  476.                   free(mail); mail=(char *) malloc(2048);
  477.                   if(scasecmp(a,"no")==0) {
  478.                       a=extract(config,"contact=",'\n');
  479.                       if(a==NULL) {
  480.                           a=(char *) malloc(6+strlen(HOST));
  481.                           sprintf(a,"root@%s",HOST);
  482.                       }
  483.                       sprintf(mail,"You may send mail to %s@%s only if you are\nsubscribed to the list.\nContact the list operator, %s.\n",to,HOST,a);
  484.                       send(to,from,listaddress,"Sending mail to this list",mail,footfile);
  485.                   } else {
  486.                       sprintf(mail,"You may send mail to %s@%s only if you are\nsubscribed to the list.\nTo subscribe, send a message to %s@%s\nwith the Subject set to 'subscribe'.\n",to,HOST,to,HOST);
  487.                       send(to,from,listaddress,"Sending mail to this list",mail,footfile);
  488.                   }
  489.               } else
  490.                   sendtolist(to,from,subject,msg);
  491.           } else {
  492.               sendtolist(to,from,subject,msg);
  493.           }
  494.       }
  495.   }
  496.   
  497.   #ifdef LOG
  498.     fclose(log);
  499.     free(logfile);
  500.   #endif
  501.  
  502.   free(mail); free(header);
  503.   free(to); free(from); free(subject);
  504.   free(listfile); free(opfile);
  505.   free(config); free(listaddress);
  506.   #ifdef GET_HOST
  507.       free(hostname);
  508.   #endif
  509.   return 0;
  510. }
  511.